package handlers

import (
	"net/http"
	"virt-manager-go/internal/console"

	"github.com/gin-gonic/gin"
	"github.com/sirupsen/logrus"
)

// ConsoleHandler handles console proxy requests
type ConsoleHandler struct {
	Proxy  *console.SerialProxy
	logger *logrus.Logger
}

func NewConsoleHandler(proxy *console.SerialProxy, logger *logrus.Logger) *ConsoleHandler {
	return &ConsoleHandler{
		Proxy:  proxy,
		logger: logger,
	}
}

// ===== 串行控制台 API =====

// GetSerialInfo 获取串行控制台信息
//
//	@Summary	Get serial console connection info
//	@Tags		Console
//	@Param		connection_id	path		string	true	"Connection ID"
//	@Param		vm_name			path		string	true	"VM Name"
//	@Success	200				{object}	console.SerialInfo
//	@Router		/api/v1/console/serial/{connection_id}/{vm_name}/info [get]
func (h *ConsoleHandler) GetSerialInfo(c *gin.Context) {
	connID := c.Param("connection_id")
	vmName := c.Param("vm_name")

	info, err := h.Proxy.GetSerialInfo(c.Request.Context(), connID, vmName)
	if err != nil {
		h.logger.WithError(err).Error("Failed to get serial console info")
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{"data": info})
}

// HandleSerialWebSocket 处理串行控制台 WebSocket 连接
//
//	@Summary	Connect to serial console via WebSocket
//	@Tags		Console
//	@Param		connection_id	path	string	true	"Connection ID"
//	@Param		vm_name			path	string	true	"VM Name"
//	@Param		token			query	string	true	"Access Token"
//	@Router		/api/v1/console/serial/{connection_id}/{vm_name} [get]
func (h *ConsoleHandler) HandleSerialWebSocket(c *gin.Context) {
	connID := c.Param("connection_id")
	vmName := c.Param("vm_name")

	if err := h.Proxy.HandleSerialWebSocket(c.Writer, c.Request, connID, vmName); err != nil {
		h.logger.WithError(err).Error("Serial console WebSocket handler error")
		// WebSocket 已经升级，不能再返回 HTTP 错误
	}
}

// ListSerialSessions 列出活跃的串行控制台会话
//
//	@Summary	List active serial console sessions
//	@Tags		Console
//	@Success	200	{array}	console.SerialSessionInfo
//	@Router		/api/v1/console/serial/sessions [get]
func (h *ConsoleHandler) ListSerialSessions(c *gin.Context) {
	sessions := h.Proxy.GetActiveSessions()
	c.JSON(http.StatusOK, gin.H{
		"data":  sessions,
		"count": len(sessions),
	})
}

// GetSerialSession 获取串行控制台会话信息
//
//	@Summary	Get serial console session info
//	@Tags		Console
//	@Param		session_id	path		string	true	"Session ID"
//	@Success	200			{object}	console.SerialSessionInfo
//	@Router		/api/v1/console/serial/sessions/{session_id} [get]
func (h *ConsoleHandler) GetSerialSession(c *gin.Context) {
	sessionID := c.Param("session_id")

	session, err := h.Proxy.GetSessionInfo(sessionID)
	if err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{"data": session})
}

// CloseSerialSession 关闭串行控制台会话
//
//	@Summary	Close serial console session
//	@Tags		Console
//	@Param		session_id	path		string	true	"Session ID"
//	@Success	200			{object}	map[string]string
//	@Router		/api/v1/console/serial/sessions/{session_id} [delete]
func (h *ConsoleHandler) CloseSerialSession(c *gin.Context) {
	sessionID := c.Param("session_id")

	if err := h.Proxy.CloseSession(sessionID); err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{"message": "Session closed"})
}

// CloseVMSerialSessions 关闭虚拟机的所有串行控制台会话
//
//	@Summary	Close all serial sessions for a VM
//	@Tags		Console
//	@Param		connection_id	path		string	true	"Connection ID"
//	@Param		vm_name			path		string	true	"VM Name"
//	@Success	200				{object}	map[string]interface{}
//	@Router		/api/v1/console/serial/{connection_id}/{vm_name}/sessions [delete]
func (h *ConsoleHandler) CloseVMSerialSessions(c *gin.Context) {
	connID := c.Param("connection_id")
	vmName := c.Param("vm_name")

	count := h.Proxy.CloseSessionsByVM(connID, vmName)

	c.JSON(http.StatusOK, gin.H{
		"message": "Sessions closed",
		"count":   count,
	})
}

// GetSerialProxyStats 获取串行控制台代理统计信息
//
//	@Summary	Get serial console proxy statistics
//	@Tags		Console
//	@Success	200	{object}	console.ProxyStats
//	@Router		/api/v1/console/serial/stats [get]
func (h *ConsoleHandler) GetSerialProxyStats(c *gin.Context) {
	stats := h.Proxy.GetStats()
	c.JSON(http.StatusOK, gin.H{"data": stats})
}

// RevokeSerialToken 撤销串行控制台访问令牌
//
//	@Summary	Revoke serial console access token
//	@Tags		Console
//	@Param		token	path		string	true	"Token"
//	@Success	200		{object}	map[string]string
//	@Router		/api/v1/console/serial/tokens/{token} [delete]
func (h *ConsoleHandler) RevokeSerialToken(c *gin.Context) {
	token := c.Param("token")

	if h.Proxy.RevokeToken(token) {
		c.JSON(http.StatusOK, gin.H{"message": "Token revoked"})
	} else {
		c.JSON(http.StatusNotFound, gin.H{"error": "Token not found"})
	}
}
